package org.angelica.exception;

import org.angelica.core.response.ResponseResult;
import org.angelica.enums.ResponseErrorEnum;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;

/**
 * 全局的的异常拦截器
 * 拦截所有的控制器，带有@RequestMapping注解的方法上都会拦截
 * @author aiken
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 服务器未知运行时异常
     * @param e 异常对象
     * @return ResponseResult
     */
    @ExceptionHandler(value = Exception.class)
    public ResponseResult handle(Exception e) {
        return ResponseResult.error(ResponseErrorEnum.UNKNOWN);
    }
    /**
     * 业务异常
     * @param e 业务异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = ServiceException.class)
    public ResponseResult handle(ServiceException e) {
        return ResponseResult.error(e.getCode(), e.getMessage());
    }

    /**
     * 请求缺少参数
     * @param e 异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResponseResult handle(MissingServletRequestParameterException e) {
        return ResponseResult.error(ResponseErrorEnum.MISSING_PARAM.getCode(),
                ResponseErrorEnum.MISSING_PARAM.getMsg() + e.getParameterName());
    }

    /**
     * HTTP请求方式错误
     * @param e 异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    public ResponseResult handle(HttpRequestMethodNotSupportedException e) {
        return ResponseResult.error(ResponseErrorEnum.HTTP_REQUEST_METHOD_NOTSUPPORTED.getCode(),
                ResponseErrorEnum.HTTP_REQUEST_METHOD_NOTSUPPORTED.getMsg() + e.getSupportedHttpMethods());
    }
    /**
     * Valid校验参数的报错
     * @param e 异常
     * @return ResponseResult
     */
    @ExceptionHandler(value = BindException.class)
    public ResponseResult handle(BindException e) {
        List<FieldError> errors = e.getFieldErrors();
        StringBuilder sbf = new StringBuilder();
        for(FieldError fe:errors) {
            sbf.append(fe.getField()).append(fe.getDefaultMessage()).append(",");
        }
        if(sbf.length()>0) {
            sbf.deleteCharAt(sbf.length()-1);
        }

        return ResponseResult.error(ResponseErrorEnum.ERROR_PARAM.getCode(),
                ResponseErrorEnum.ERROR_PARAM.getMsg()+sbf.toString());
    }
}
